#include <QApplication>
#include <QString>
#include <QStringList>
#include <QPushButton>
#include <QEventLoop>

#include "pop_window_manager.h"
#include "device_monitor.h"
#include "new_pop_window.h"
#include "common.h"
#include "find_and_match_ppds.h"
#include "ukui_printer.h"
#include "ukui_apt.h"
#include "mainwindow.h"

PopWindowManager::PopWindowManager()
{
    initConnection();
}

void PopWindowManager::initConnection()
{
    connect(DeviceMonitor::getInstance(), &DeviceMonitor::findUsbConnect, 
            this,                         &PopWindowManager::getDevInfo);
    connect(DeviceMonitor::getInstance(), &DeviceMonitor::findUsbDisconnect, 
            this,                         &PopWindowManager::modifyInfoList);
    connect(this, &PopWindowManager::showNextRequest, 
            this, &PopWindowManager::showNext);
}

void PopWindowManager::getDevInfo(DeviceInformation &devInfo)
{
    if (m_infoList.isEmpty()) {
        m_widCnt = 0;
        m_infoList.append(devInfo);
        showPopWindow(m_infoList.at(m_widCnt));
    }
    else {
        // 先判断之前有没有处理过
        for (int i = 0; i < qMin(m_widCnt, m_infoList.size()); i++) {
            if (devInfo.sysPath == m_infoList.at(i).sysPath) {
                return ;
            }
        }
        m_infoList.append(devInfo);
    }
    return ;
}

void PopWindowManager::modifyInfoList(QString &path)
{
    // 如果第一个参数是remove直接退
    if (m_infoList.isEmpty()) {
        this->~PopWindowManager();
        return ;
    }
    // 只需要处理widCnt后面的数据
    for (int i = qMax(m_widCnt + 1, 0); i < m_infoList.size(); i++) {
        if (path == m_infoList.at(i).sysPath) {
            m_infoList.removeAt(i);
            return ;
        }
    }
    return ;
}

void PopWindowManager::showNext()
{
    m_widCnt++;
    if (m_widCnt >= m_infoList.size()) {
        qDebug() << "popwindow show all finished!";
        this->~PopWindowManager();
        return ;
    }
    showPopWindow(m_infoList.at(m_widCnt));
    return ;
}

void PopWindowManager::showPopWindow(const DeviceInformation &devInfo)
{
    qDebug() << "Installing: " <<devInfo.name;
    if(MainWindow::getInstance()->mainWindowIsHidden()==false) {
        showNextRequest();
        qDebug() << "In Installing: " << devInfo.name << " ,main window is showing";
        return;
    }

    // 判断一下是否重复了
    QList<DeviceInformation> res;
    res = DeviceMonitor::getAllPrinterWithPDD(true);
    for (int i = 0 ;i < res.count(); i++) {
        if(devInfo.uri == res.at(i).uri) {
            qDebug() << "In Installing: " << devInfo.name;
            qDebug()<<"The Printer: "<<devInfo.uri << " has already installed!";
            showNextRequest();
            return ;
        }
    }

    // 信息复制
    DeviceInformation popDevInfo = devInfo;
    // qDebug() << popDevInfo;
    // 设置打印机名字
    // 打印机名称和型号中不能有空格
    // 替换为“-”再继续
    popDevInfo.vendor = (popDevInfo.vendor).replace(QRegExp("\\s"),"-");
    popDevInfo.model = (popDevInfo.model).replace(QRegExp("\\s"),"-");
    if (popDevInfo.vendor.isEmpty() || popDevInfo.model.isEmpty()) {
        showNextRequest();
        if (popDevInfo.vendor.isEmpty()) {
            qDebug() << "In Installing: " << devInfo.name << " ,vendor is empty!";
        }
        if (popDevInfo.model.isEmpty()) {
            qDebug() << "In Installing: " << devInfo.name << " ,model is empty!";
        }
        return ;
    }

    popDevInfo.name = popDevInfo.vendor + QString("-") + popDevInfo.model;

    NewPopWindow *w = new NewPopWindow(popDevInfo);
    connect(w, &NewPopWindow::manualInstallRequest, this, [=, &popDevInfo](){
        emit this->manualInstallShowRequest(popDevInfo);
    });
    // qDebug() << popDevInfo;
    connect(w, &NewPopWindow::deviceViewRequest, this, [=, &popDevInfo](){
        // qDebug() << popDevInfo;
        emit this->deviceViewShowRequest(popDevInfo.name);
    });

    // 打印机流程
    w->Show(PopWinStatus::INSTALLING);

    bool needUpdatePpdMap = false;
    if (!installPackage(devInfo)){
        qDebug() << "In Installing: " << devInfo.name << " ,install deb failed!";
        needUpdatePpdMap = false;
    }
    else {
        needUpdatePpdMap = true;
    }

    QString accuratelyMatchPPD;
    QStringList fuzzyMatchPPDlis;

    if (false == findPPD(needUpdatePpdMap,
                         popDevInfo.vendor,
                         popDevInfo.model,
                         accuratelyMatchPPD, 
                         fuzzyMatchPPDlis)) {

        qDebug() << "In Installing: " << devInfo.name << " ,find ppd failed!";
        w->Show(PopWinStatus::INSTALL_FAIL);
        return ;
    }

    if(accuratelyMatchPPD.isEmpty()==false){
        if (false == UkuiPrinterManager::getInstance().addPrinter(
                     popDevInfo.uri,
                     popDevInfo.name,
                     accuratelyMatchPPD,
                     "")) {
            
            qDebug() << "In Installing: " << devInfo.name << " ,add printer failed!";
            w->Show(PopWinStatus::INSTALL_FAIL);
        }
        else
            w->Show(PopWinStatus::INSTALL_SUCCESS);
    }
    else {
        w->Show(PopWinStatus::INSTALL_FAIL);
    }
    return ;
}

bool PopWindowManager::findPPD(bool needUpdatePpdMap,
                               const QString &vendor,
                               const QString &model,
                               QString &accuratelyMatchPPD,
                               QStringList &fuzzyMatchPPDlis)
{
    try
    {
        g_findAndMatchWorkThread->start();
    }
    catch(const std::exception& e)
    {
        g_findAndMatchWorkThread->deleteLater();
        std::cerr << e.what() << '\n';
        qApp->exit(0);
    }

    ppdPrinterMap currentPPDsMap;

    if(!g_findAndMatchWorkThread->hasPPDsMap() || needUpdatePpdMap) {
        g_findAndMatchWorkThread->updatePPDsMap();
        QEventLoop eventloop;
        QObject::connect(g_findAndMatchWorkThread, &FindAndMatchPPDs::updateFinished,
                &eventloop, &QEventLoop::quit);
        eventloop.exec();
    }

    if( g_findAndMatchWorkThread->hasPPDsMap())
    {
        if(static_cast<int>(FindAndMatchStatus::OPERATION_OK) == g_findAndMatchWorkThread->getCurrentPPDsMap(currentPPDsMap))
        {
            // qDebug() << "get PPD`s Map";
            g_findAndMatchWorkThread->matchPPDToPrinter(vendor,
                                                        model,
                                                        accuratelyMatchPPD,
                                                        fuzzyMatchPPDlis);
            return true;
        }
        else
        {
            qDebug() << "get PPD`s Map failed";
            return false;
        }
    }
    return false;
}

bool PopWindowManager::installPackage(const DeviceInformation &devInfo)
{
    bool install = false;
    AptUtilHelper* aptHelper = new AptUtilHelper(devInfo);
    QEventLoop eventloop;

    QObject::connect(aptHelper, &AptUtilHelper::succeed, [&devInfo, &eventloop, &install]() {
        // qDebug() << devInfo.name <<"`s package: Install succeed";
        install = true;
        eventloop.quit();
    });
    QObject::connect(aptHelper, &AptUtilHelper::failed, [&devInfo, &eventloop, &install]() {
        // qDebug() << devInfo.name <<"`s package: Install failed";
        install = false;
        eventloop.quit();
    });
    aptHelper->startWorker();
    eventloop.exec();
    return install;
}


PopWindowManager *PopWindowManager::getInstance()
{
    static PopWindowManager *instance = nullptr;
    if (nullptr == instance) {
        instance = new PopWindowManager();
    }
    return instance;
}

PopWindowManager::~PopWindowManager()
{
    if(MainWindow::getInstance()->mainWindowIsHidden()==true){
        exit(0);
    }
}
